// 这里的代码很重要，必须亲力亲为自己写
// 核心：路由守卫
// 全局前置守卫

// 导入router实例和动态路由表
import router from '@/router/index'

// 导入store实例
import store from '@/store/index'

// 导入 nprogress 模块(进入页面的加载提示)
import NProgress from 'nprogress'
// 导入 nprogress 样式
import 'nprogress/nprogress.css'

// 定义白名单，放的是无需登录就可访问的路由路径
const whiteList = ['/login', '/404']

// 注册全局前置守卫
router.beforeEach(async(to, from, next) => {
  // 开启进度条的加载提示
  NProgress.start()
  // 获取token(从vuex中获取)
  const { token } = store.state.user
  // 判断
  if (token) { // 登陆了
    // 判断：如果要去的路由路径在白名单中，就没必要去了，直接去首页，否则放行
    if (to.path === '/login') {
      // 直接去首页
      next('/')
      NProgress.done()
    } else {
      // 获取用户信息的 action 函数在这里调用
      // 注意：
      // 1.此项目核心在权限控制，就是不同员工登陆进来看到的主页菜单不同
      // 2.如果员工登陆成功了，已经跳转至主页再发请求，再获取员工的角色权限信息已经太晚了
      // 3.这个获取员工的角色权限信息的时机是在跳转至主页之前拿到当前员工的角色信息，知道你是谁了，有哪些权限，
      //   然后再对应的开放左侧菜单，这些操作都做完了再让员工跳转至首页，这时员工看到的左侧菜单栏就是关于ta具备的权限
      // 4.只是现在还不知道如何开放对应的菜单，这里先留着(原理：基于员工的角色列表信息(动态路由表)筛选权限) todo

      // 当路由切换时会发起多次无效请求，需要优化
      // 如果用户信息有了，就不再发请求；如果没有用户信息才发起一次请求
      // 第1种方式：判断 vuex 中的 userId 有没有
      if (!store.state.user.userInfo.userId) {
        await store.dispatch('user/userInfoAction')
        // 这里拿到了用户信息，用户信息有个 userInfo.roles.menus 可以拿到当前员工的角色列表
        // 这个角色列表数组中的字符串表明了当前员工可以看到的左侧菜单
        // 今后基于这个数组对动态路由做筛选，然后再跳至首页，这样主页展示的左侧菜单就是当前员工能看到的
        // 获取当前用户的 menus 数组
        const { menus } = store.state.user.userInfo.roles
        // 基于当前用户信息中roles.menus数组来动态筛选路由表
        // 筛选的条件：判断当前路由第一个children的名字是否在menus数组中
        // 在的话就留下(拥有的权限/菜单)；否则就过滤掉
        // 触发route/asyncRoutesAction
        // 从vuex中获取所有需要展示的路由表(左侧菜单)，并且是响应式的
        const showAsyncRoutes = await store.dispatch('route/asyncRoutesAction', menus)

        // 把筛选完毕的动态路由表再动态追加到路由表中，这样今后输入path才能访问到
        // router.addroutes(路由对象数组)：同时追加多个路由规则到数组中
        // router.addroute(路由对象)：追加一个路由规则到路由表中
        router.addRoutes([
          ...showAsyncRoutes,
          // 能永远让404页面在最后面
          { path: '*', redirect: '/404', hidden: true }
        ])
        // 刷新路由表
        next({
          ...to, // 保留原有的所有要去的路由信息，并保证路由添加完了再进入页面
          replace: true // 替换刚才那一次跳转的历史记录
        })
      }
      // 第2种方式：拿到 action 函数的返回值
      // 注意：所有的action返回的都是promise实例，需要加await获取
      // const userObj = await store.dispatch('user/userInfoAction')
      // 判断userObj中是否存在userId，如果没有再发请求

      // 放行
      next()
    }
  } else { // 未登录
    // 进一步判断(要去的路径是否在白名单中)
    if (whiteList.includes(to.path)) {
      // 如果在，放行
      next()
    } else {
      // 否则跳转至登录，并携带回跳地址
      next(`/login?redirectUrl=${to.path}`)
      NProgress.done()
    }
  }
})

// 注册后置全局守卫
router.afterEach(() => {
  // 关闭进度条提示
  NProgress.done()
})

